﻿#region Copyright Notice
// 
// 
// Copyright (c) 2009-2010 Anindya Chatterjee
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// 
// 
// 
#endregion
using System;
using System.IO;
using System.Reflection;
using System.Serialization.Xml;
using System.Windows.Forms;
using DesktopNotifier.Settings;
using DesktopNotifier.Utility;
using Event.Plugin;
using Event.Plugin.Configuration;
using Event.Plugin.Utility;

namespace DesktopNotifier
{
    /// <summary>
    /// This class will load each events and register it with the application
    /// </summary>
    public class EventManager : IEventHost
    {
        private readonly AppConfig _config;
        private readonly EventDescriptor _descriptor;
        private readonly INotifier _notifier;
        private IEvent[] _iEvents;

        public EventManager(AppConfig config)
        {
            _descriptor = XObjectSerializer<EventDescriptor>.ReadFile(Constants.Descriptor);
            _notifier = new NotifyUtility();
            _config = config;

            // safe mode measurements
            SafeModeMeasure();
        }

        #region IEventHost Members

        public bool Register(AbstractEvent iEvent)
        {
            EventListener.RegisterEvent(iEvent);
            return true;
        }

        #endregion

        private void SafeModeMeasure()
        {
            if (!_config.SafeMode)
                Load();
            else
            {
                foreach (Plugin item in _descriptor.Plugin)
                {
                    item.Enable = false;
                }
                XObjectSerializer<EventDescriptor>.WriteFile(Constants.Descriptor, _descriptor);
            }
            _config.SafeMode = false;
        }

        internal void Load()
        {
            string path = Application.StartupPath + @"\Events";
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);
            string[] pluginFiles = Directory.GetFiles(path, "*.dll");
            _iEvents = new IEvent[pluginFiles.Length];

            for (int i = 0; i < pluginFiles.Length; i++)
            {
                pluginFiles[i] = pluginFiles[i].ToLower();
                string args = pluginFiles[i].Substring(
                    pluginFiles[i].LastIndexOf("\\") + 1,
                    pluginFiles[i].IndexOf(".dll") -
                    pluginFiles[i].LastIndexOf("\\") - 1);

                if (!IsPluginEnabled(args, _descriptor))
                    continue;

                Type objTypeEvent = null;
                try
                {
                    string fileName = path + "\\" + args + ".dll";
                    Assembly assembly = Assembly.LoadFrom(fileName);
                    if (assembly != null)
                    {
                        Type[] types = assembly.GetTypes();
                        foreach (Type type in types)
                        {
                            if (type.BaseType == typeof (AbstractEvent))
                            {
                                objTypeEvent = type;
                                break;
                            }
                        }
                    }
                    if (objTypeEvent != null)
                    {
                        _iEvents[i] = (AbstractEvent) Activator.CreateInstance(objTypeEvent);
                        _iEvents[i].Host = this;
                        _iEvents[i].Name = args;
                        _iEvents[i].UserNotifier = _notifier;
                        _iEvents[i].ApplicationSettings = _config;
                        _iEvents[i].UnhandledExceptionHandler = HandleUnhandledException;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error in Ozone");
                }
            }
        }

        private static bool IsPluginEnabled(String plugin, EventDescriptor descriptor)
        {
            foreach (Plugin item in descriptor.Plugin)
            {
                if (item.Name.Equals(plugin, StringComparison.InvariantCultureIgnoreCase))
                    return item.Enable;
            }
            return false;
        }

        private void HandleUnhandledException(IEvent sender, Exception ex)
        {
            new BugReport(sender, _config) {Bug = ex, StartPosition = FormStartPosition.CenterScreen}.ShowDialog();
        }
    }
}